package com.dzl.order;

import com.alibaba.fastjson.JSONObject;
import com.dzl.config.ApplicationConfiguration;
import com.dzl.constant.WelfareOrderStatusEnum;
import com.dzl.constant.WelfareOrderTypeEnum;
import com.dzl.operation.service.OperationLogService;
import com.dzl.order.pojo.WelfareOrder;
import com.dzl.order.pojo.dto.*;
import com.dzl.order.pojo.query.WelfareOrderUserQuery;
import com.dzl.order.pojo.vo.*;
import com.dzl.order.service.WelfareOrderService;
import com.dzl.userwx.pojo.WelfareUserWx;
import com.dzl.userwx.service.WelfareUserWxService;
import com.dzl.util.EmptyUtils;
import com.dzl.util.JsonResult;
import com.dzl.util.PageUtils;
import com.dzl.util.wx.WxConfig;
import com.dzl.util.wx.wxpay.WXPayConstants;
import com.dzl.util.wx.wxpay.WXPayUtil;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.dzl.base.controller.BaseController;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;


/**
 * 订单表(WelfareOrder)表控制层
 * @author ChenLong
 * @date 2021-05-21 15:33:35
 */
@Slf4j
@RestController
@RequestMapping("/welfareOrder")
public class WelfareOrderController extends BaseController {

    @Autowired
    private WelfareOrderService welfareOrderService;
    @Autowired
    private WelfareUserWxService welfareUserWxService;
    @Autowired
    private OperationLogService operationLogService;

    /**
     * 取消订单
     * @param welfareOrderCancelDto 订单取消id
     * @return com.dzl.util.JsonResult
     * @author ChenLong
     * @date 2021-06-09 16:05:52
     **/
    @PostMapping(value = "cancelOrderById")
    public JsonResult<Object> cancelOrderById(@RequestBody WelfareOrderCancelDto welfareOrderCancelDto) {
        log.info("cancelOrderById in id: " + welfareOrderCancelDto);
        if (EmptyUtils.isEmpty(welfareOrderCancelDto) || EmptyUtils.isEmpty(welfareOrderCancelDto.getId()) || EmptyUtils.isEmpty(welfareOrderCancelDto.getOrderType())) {
            return JsonResult.paramErrWithMsg("参数错误");
        }
        Integer userId = getWxUserInfo().getId();
        welfareOrderCancelDto.setUserId(userId);
        int resCode = welfareOrderService.cancelOrderByOrderId(welfareOrderCancelDto);
        if (resCode > 0) {
            return JsonResult.success();
        } else {
            return JsonResult.failWithMsg("操作失败");
        }
    }

    /**
     * 确定收货
     * @param id 订单id
     * @return com.dzl.util.JsonResult
     * @author ChenLong
     * @date 2021-06-09 16:05:52
     **/
    @PostMapping(value = "updateOrderCompleteById")
    public JsonResult<Object> updateOrderCompleteById(Integer id) {
        log.info("cancelOrderById in id: " + id);
        if (EmptyUtils.isEmpty(id)) {
            return JsonResult.paramErrWithMsg("参数错误");
        }
        WelfareOrder welfareOrderRes = welfareOrderService.selectByPrimaryKey(id);
        // 只有在待收获状态订单才能确认收货
        if (EmptyUtils.isNotEmpty(welfareOrderRes) && !welfareOrderRes.getOrderStatus().equals(WelfareOrderStatusEnum.ORDER_STATUS_SHIPED.getCode())) {
            return JsonResult.failWithMsg("请检查订单状态");
        }
        Integer userId = getWxUserInfo().getId();
        WelfareOrder welfareOrder = new WelfareOrder();
        welfareOrder.setId(id);
        welfareOrder.setUserId(userId);
        welfareOrder.setOrderStatus(WelfareOrderStatusEnum.ORDER_STATUS_COMPLETED.getCode());
        welfareOrder.setUpdateTime(new Date());
        int resCode = welfareOrderService.updateByPrimaryKeySelective(welfareOrder);
        if (resCode > 0) {
            return JsonResult.success();
        } else {
            return JsonResult.failWithMsg("操作失败");
        }
    }

    /**
     * 获取用户的订单列表
     * @param query 用户id、订单状态
     * @return com.dzl.util.PageUtils
     * @author ChenLong
     * @since 2021-05-21 17:14:22
     **/
    @GetMapping(value = "getOrderGoodsList")
    public PageUtils<WelfareOrderGoodsListVo> getOrderGoodsList(WelfareOrderUserQuery query) {
        log.info("getOrderGoodsList in query: " + query.toString());
        Integer userId = getWxUserInfo().getId();
        query.setUserId(userId);
        query.setStatus(1);
        List<WelfareOrderGoodsListVo> list = welfareOrderService.getOrderGoodsListByUserId(query);
        PageInfo<WelfareOrderGoodsListVo> pageInfo = new PageInfo<>(list);
        return new PageUtils<>(pageInfo);
    }

    /**
     * 获取用户的订单详情
     * @param orderId 订单id
     * @return com.dzl.util.PageUtils
     * @author ChenLong
     * @since 2021-05-21 17:14:22
     **/
    @GetMapping(value = "getOrderGoodsListByOrderId")
    public JsonResult<WelfareOrderGoodsDetailVo> getOrderGoodsListByOrderId(Integer orderId) {
        log.info("getOrderGoodsListByOrderId in orderId: " + orderId);
        Integer userId = getWxUserInfo().getId();
        WelfareOrderUserQuery query = new WelfareOrderUserQuery();
        query.setOrderId(orderId);
        query.setUserId(userId);
        query.setStatus(1);
        return JsonResult.success(welfareOrderService.getOrderGoodsListByOrderId(query));
    }

    /**
     * 获取用户的订单详情
     * @param orderId 订单id
     * @return com.dzl.util.PageUtils
     * @author ChenLong
     * @since 2021-05-21 17:14:22
     **/
    @GetMapping(value = "getExchangeOrderPayInfoByOrderId")
    public JsonResult<WelfareOrderExchangeVo> getExchangeOrderPayInfoByOrderId(Integer orderId) {
        log.info("getExchangeOrderPayInfoByOrderId in orderId: " + orderId);
        return JsonResult.success(welfareOrderService.getExchangeOrderPayInfoByOrderId(orderId));
    }

    /**
     * 用户下单（兑换订单）
     * @param welfareOrderExchangeDto 用户下单DTO实体类
     * @return com.dzl.util.JsonResult
     * @author ChenLong
     * @since 2021-05-21 15:40:28
     **/
    @PostMapping(value = "updateExchangeOrder")
    public JsonResult<Integer> updateExchangeOrder(@RequestBody WelfareOrderExchangeDto welfareOrderExchangeDto) {
        log.info("updateExchangeOrderAndSplit in welfareOrderExchangeDto: " + welfareOrderExchangeDto.toString());
        Map resMap = welfareOrderService.updateExchangeOrderAndSplit(welfareOrderExchangeDto);
        Integer resCode = Integer.parseInt(resMap.get("code").toString());
        String msg = resMap.get("msg").toString();
        if (resCode.equals(1)) {
            Integer orderId = Integer.parseInt(resMap.get("orderId").toString());
            // 发送短信（兑换虚拟订单发送兑换码）
            WelfareOrder welfareOrder = welfareOrderService.selectByPrimaryKey(orderId);
            if (EmptyUtils.isNotEmpty(welfareOrder)) {
                welfareOrderService.sendMessageForPayByOrder(welfareOrder);
            }
            return JsonResult.success(orderId);
        } else {
            return JsonResult.failWithMsg(msg);
        }
    }

    /**
     * 用户下单
     * @param welfareOrderDto 用户下单DTO实体类
     * @return com.dzl.util.JsonResult
     * @author ChenLong
     * @since 2021-05-21 15:40:28
     **/
    @PostMapping(value = "addUserOrder")
    public JsonResult<Integer> addUserOrder(@RequestBody WelfareOrderDto welfareOrderDto) {
        log.info("addUserOrder in welfareOrderDto: " + welfareOrderDto.toString());
        Integer userId = getWxUserInfo().getId();
        welfareOrderDto.setUserId(userId);
        welfareOrderDto.setEnterpriseId(getWxUserInfo().getEnterpriseId());
        Map resMap = welfareOrderService.addUserOrder(welfareOrderDto);
        Integer resCode = Integer.parseInt(resMap.get("code").toString());
        String msg = resMap.get("msg").toString();
        if (resCode.equals(1)) {
            Integer orderId = Integer.parseInt(resMap.get("orderId").toString());
            return JsonResult.success(orderId);
        } else {
            return JsonResult.failWithMsg(msg);
        }
    }

    /**
     * 获取订单支付卡商品默认匹配结果
     * @param orderId 订单id
     * @return com.dzl.util.JsonResult
     * @author ChenLong
     * @date 2021-05-25 20:17:09
     **/
    @GetMapping(value = "addOrderGoodsPayMatchByOrderId")
    public JsonResult<WelfareOrderGoodsPayVo> addOrderGoodsPayMatchByOrderId(Integer orderId) {
        log.info("WelfareOrderGoodsPayVo in orderId: " + orderId);
        Integer userId = getWxUserInfo().getId();
        if (EmptyUtils.isEmpty(orderId)) {
            return JsonResult.paramErrWithMsg("参数错误");
        }
        Map resMap = welfareOrderService.addOrderGoodsPayMatchByOrderId(userId, orderId);
        Integer resCode = Integer.parseInt(resMap.get("code").toString());
        String msg = resMap.get("msg").toString();
        if (resCode.equals(1)) {
            return JsonResult.success((WelfareOrderGoodsPayVo) resMap.get("data"));
        } else {
            return JsonResult.failWithMsg(msg);
        }
    }

    /**
     * 订单支付卡商品匹配结果重新计算
     * @param welfareOrderGoodsPayMatchDto 查询实体
     * @return com.dzl.util.JsonResult<java.lang.Object>
     * @author ChenLong
     * @date 2021-05-25 20:17:46
     **/
    @PostMapping(value = "addOrderGoodsPayMatchReDefine")
    public JsonResult<WelfareOrderGoodsPayVo> addOrderGoodsPayMatchReDefine(@RequestBody WelfareOrderGoodsPayMatchDto welfareOrderGoodsPayMatchDto) {
        log.info("addOrderPayValidCalculate in welfareOrderGoodsPayMatchDto: " + welfareOrderGoodsPayMatchDto.toString());
        Integer userId = getWxUserInfo().getId();
        WelfareOrderGoodsPayVo welfareOrderGoodsPayVo = welfareOrderService.addOrderGoodsPayMatchReDefine(userId, welfareOrderGoodsPayMatchDto);
        return JsonResult.success(welfareOrderGoodsPayVo);
    }

    /**
     * 订单支付确认
     * @param welfareOrderPayMatchDto 查询实体
     * @return com.dzl.util.JsonResult<java.lang.Object>
     * @author ChenLong
     * @date 2021-05-25 20:18:37
     **/
    @PostMapping(value = "addOrderConfirmForPay")
    public JsonResult<Integer> addOrderConfirmForPay(@RequestBody WelfareOrderGoodsPayMatchDto welfareOrderPayMatchDto) {
        log.info("addOrderConfirmForPay in welfareOrderPayMatchDto: " + welfareOrderPayMatchDto);
        Integer userId = getWxUserInfo().getId();
        if (EmptyUtils.isNotEmpty(welfareOrderPayMatchDto.getCardGoodsList()) && welfareOrderPayMatchDto.getCardGoodsList().size() > 0) {
            WelfareUserWx welfareUserWxRes = welfareUserWxService.selectByPrimaryKey(userId);
            if (EmptyUtils.isEmpty(welfareUserWxRes) || EmptyUtils.isEmpty(welfareUserWxRes.getPayPassword())) {
                return JsonResult.failWithMsg("请设置支付密码");
            }
        }
        int resCode = welfareOrderService.addOrderConfirmForPay(userId, welfareOrderPayMatchDto);
        if (resCode == 1) {
            return JsonResult.success();
        } else {
            return JsonResult.failWithMsg("操作失败");
        }
    }

    /**
     * 确认支付
     * @param welfareOrderPayConfirmDto 订单id
     * @return com.dzl.util.JsonResult
     * @author ChenLong
     * @date 2021-05-26 12:24:35
     **/
    @PostMapping("/addPaymentExecute")
    public JsonResult addPaymentExecute(@RequestBody WelfareOrderPayConfirmDto welfareOrderPayConfirmDto) {
        log.info("addPaymentExecute in welfareOrderPayConfirmDto: " + welfareOrderPayConfirmDto);
        if (null == welfareOrderPayConfirmDto) {
            return JsonResult.paramErr("参数错误");
        }
        if (EmptyUtils.isEmpty(welfareOrderPayConfirmDto.getOrderId()) || EmptyUtils.isEmpty(welfareOrderPayConfirmDto.getType())) {
            return JsonResult.paramErr("参数错误");
        }
        WelfareUserWx welfareUserWx = getWxUserInfo();
        Map resMap = welfareOrderService.addPaymentExecute(welfareOrderPayConfirmDto.getOrderId(), welfareOrderPayConfirmDto.getType(), welfareUserWx.getOpenId());
        Integer resCode = Integer.parseInt(resMap.get("code").toString());
        String msg = resMap.get("msg").toString();
        if (resCode.equals(1)) {
            // 发送短信（兑换虚拟订单发送兑换码）
            WelfareOrder welfareOrder = welfareOrderService.selectByPrimaryKey(welfareOrderPayConfirmDto.getOrderId());
            // 如果是补差支付，微信回调成功以后再发短信
            if (EmptyUtils.isNotEmpty(welfareOrder) && !welfareOrderPayConfirmDto.getType().equals(2) && !welfareOrder.getOrderType().equals(WelfareOrderTypeEnum.ORDER_TYPE_VIRTUAL_API_RECHARGE.getCode())) {
                welfareOrderService.sendMessageForPayByOrder(welfareOrder);
            }
            return JsonResult.success(resMap);
        } else {
            return JsonResult.failWithMsg(msg);
        }
    }

    /**
     * 获取订单支付信息
     * @param orderId 订单id
     * @return com.dzl.util.JsonResult
     * @author ChenLong
     * @date 2021-05-25 20:17:09
     **/
    @GetMapping(value = "getOrderPayMatchForIntegral")
    public JsonResult<WelfareOrderGoodsPayVo> getOrderPayMatchForIntegral(Integer orderId) {
        log.info("WelfareOrderGoodsPayVo in orderId: " + orderId);
        Integer userId = getWxUserInfo().getId();
        if (EmptyUtils.isEmpty(orderId)) {
            return JsonResult.paramErrWithMsg("参数错误");
        }
        return JsonResult.success(welfareOrderService.getOrderPayMatchForIntegral(userId,orderId));
    }

    /**
     * 支付确认
     * @param orderId 订单id
     * @return com.dzl.util.JsonResult
     * @author ChenLong
     * @date 2021-05-25 20:17:09
     **/
    @PostMapping("/addOrderConfirmPayForIntegral")
    public JsonResult addOrderConfirmPayForIntegral(Integer orderId) {
        log.info("addOrderConfirmPayForIntegral in orderId: " + orderId);
        WelfareUserWx welfareUserWx = getWxUserInfo();
        // 写入均摊
        welfareOrderService.addOrderConfirmPayForIntegral(orderId,welfareUserWx.getId());
        return JsonResult.success();
    }

    /**
     * 确认支付
     * @param welfareOrderPayConfirmDto 订单id
     * @return com.dzl.util.JsonResult
     * @author ChenLong
     * @date 2021-05-26 12:24:35
     **/
    @PostMapping("/addPayExecuteForIntegral")
    public JsonResult addPayExecuteForIntegral(@RequestBody WelfareOrderPayConfirmDto welfareOrderPayConfirmDto) {
        log.info("addPaymentExecute in welfareOrderPayConfirmDto: " + welfareOrderPayConfirmDto);
        if (null == welfareOrderPayConfirmDto) {
            return JsonResult.paramErr("参数错误");
        }
        if (EmptyUtils.isEmpty(welfareOrderPayConfirmDto.getOrderId()) || EmptyUtils.isEmpty(welfareOrderPayConfirmDto.getType())) {
            return JsonResult.paramErr("参数错误");
        }
        WelfareUserWx welfareUserWx = getWxUserInfo();
        // 执行支付（支付完以后拆单、扣减库存、释放预占、扣减卡余额）
        Map resMap = welfareOrderService.addPaymentExecute(welfareOrderPayConfirmDto.getOrderId(), welfareOrderPayConfirmDto.getType(), welfareUserWx.getOpenId());
        Integer resCode = Integer.parseInt(resMap.get("code").toString());
        String msg = resMap.get("msg").toString();
        if (resCode.equals(1)) {
            // 发送短信（兑换虚拟订单发送兑换码）
            WelfareOrder welfareOrder = welfareOrderService.selectByPrimaryKey(welfareOrderPayConfirmDto.getOrderId());
            // 如果是补差支付，微信回调成功以后再发短信
            if (EmptyUtils.isNotEmpty(welfareOrder) && !welfareOrderPayConfirmDto.getType().equals(2) && !welfareOrder.getOrderType().equals(WelfareOrderTypeEnum.ORDER_TYPE_VIRTUAL_API_RECHARGE.getCode())) {
                welfareOrderService.sendMessageForPayByOrder(welfareOrder);
            }
            return JsonResult.success(resMap);
        } else {
            return JsonResult.failWithMsg(msg);
        }
    }

    /**
     * 微信支付回调接口
     * @param request 回调request对象
     * @return java.lang.String
     * @author ChenLong
     * @date 2021-05-26 12:25:14
     **/
    @RequestMapping("/updateSettlementNotify")
    public String updateSettlementNotify(HttpServletRequest request) throws Exception {
        log.info("updateSettlementNotify in");
        request.setCharacterEncoding("utf-8");
        BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream()));
        String line;
        StringBuilder sb = new StringBuilder();
        while ((line = br.readLine()) != null) {
            sb.append(line);
        }
        log.info("updateSettlementNotify xml: " + sb.toString());
        Map<String, String> map = WXPayUtil.readStringXmlOut(sb.toString());
        String outTradeNo = map.get("out_trade_no");
        String transactionId = map.get("transaction_id");
        String totalFee = map.get("total_fee");
        // 微信支付日志JSONObject
        JSONObject logJsonObj = new JSONObject();
        if (StringUtils.isBlank(outTradeNo) || StringUtils.isBlank(transactionId)) {
            logJsonObj.put("msg", "call back for outTradeNo or transactionId blank");
            logJsonObj.put("result", map);
            operationLogService.saveOrderReturnFail(0, "WeChat callback failed: " + logJsonObj.toString());
            log.info("updateSettlementNotify params error outTradeNo :{}, transactionId :{}", outTradeNo, transactionId);
            return WXPayConstants.FAIL;
        }
        // 校验参数
        Map<String, String> validateMap = WXPayUtil.xmlToMap(sb.toString());
        if (!WXPayUtil.isSignatureValid(validateMap, WxConfig.WX_PARTNER_KEY)) {
            logJsonObj.put("msg", "call back for isSignatureValid fail");
            logJsonObj.put("result", map);
            operationLogService.saveOrderReturnFail(0, "WeChat callback failed: " + logJsonObj.toString());
            log.info("updateSettlementNotify isSignatureValid fail");
            return WXPayConstants.FAIL;
        }
        // 校验订单支付状态
        WelfareOrder query = new WelfareOrder();
        query.setOutTradeNo(outTradeNo);
        WelfareOrder welfareOrder = welfareOrderService.selectOne(query);
        // 订单状态发生了变化
        if (null == welfareOrder || !welfareOrder.getOrderStatus().equals(WelfareOrderStatusEnum.ORDER_STATUS_UNPAY.getCode())) {
            logJsonObj.put("msg", "call back for welfareOrder is null or error status");
            logJsonObj.put("result", map);
            Integer orderId = 0;
            if (EmptyUtils.isNotEmpty(welfareOrder) && EmptyUtils.isNotEmpty(welfareOrder.getId())) {
                orderId = welfareOrder.getId();
            }
            operationLogService.saveOrderReturnFail(orderId, "WeChat callback message: " + logJsonObj.toString());
            log.info("updateSettlementNotify welfareOrder is null or error status");
            return WXPayConstants.SUCCESS;
        }
        // 正式服校验支付金额
        if (!"0".equals(ApplicationConfiguration.getInstance().getIsProduct()) && (null == totalFee || !WXPayUtil.calcWxPayPrice(welfareOrder.getPaymentAmount()).toString().equals(totalFee))) {
            logJsonObj.put("msg", "call back for getInstance null");
            logJsonObj.put("result", map);
            operationLogService.saveOrderReturnFail(welfareOrder.getId(), "WeChat callback failed: " + logJsonObj.toString());
            log.info("updateSettlementNotify getInstance null");
            return WXPayConstants.FAIL;
        }
        welfareOrder.setOtherTradeNo(transactionId);
        welfareOrder.setPaymentAmount(new BigDecimal(totalFee).divide(new BigDecimal(100), 2, BigDecimal.ROUND_DOWN));
        try {
            welfareOrderService.updateOrderAndSplitForPay(welfareOrder);
            // 发送短信（兑换虚拟订单发送兑换码）、充值类的不发验证码
            if (!welfareOrder.getOrderType().equals(WelfareOrderTypeEnum.ORDER_TYPE_VIRTUAL_API_RECHARGE.getCode())) {
                welfareOrderService.sendMessageForPayByOrder(welfareOrder);
            }
            operationLogService.saveOrderReturnSuccess(welfareOrder.getId(), "WeChat callback success: " + map);
            log.info("updateSettlementNotify WeChat callback success: " + map);
            return WXPayConstants.SUCCESS;
        } catch (Exception e) {
            operationLogService.saveOrderReturnFail(welfareOrder.getId(), "WeChat callback failed: " + map);
            log.info("updateSettlementNotifyWeChat callback failed: " + map);
            return WXPayConstants.FAIL;
        }
    }

    /**
     * 查看订单状态
     * @param orderId 订单id
     * @return com.dzl.util.JsonResult
     * @author ChenLong
     * @date 2021-05-26 12:25:44
     **/
    @GetMapping("/getSettlementStatus")
    public JsonResult getSettlementStatus(Integer orderId) {
        log.info("getSettlementStatus in orderId: " + orderId);
        if (null == orderId) {
            return JsonResult.paramErr();
        }
        return JsonResult.success(welfareOrderService.selectByPrimaryKey(orderId).getOrderStatus());
    }
}
